package com.study.spring.forkjoin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class CountTask extends RecursiveTask<Long> {


    private static final Logger LOGGER = LoggerFactory.getLogger(CountTask.class);

    private static final int THRESHOLD = 1000000;

    private final int start;
    private final int end;

    public CountTask(int start, int end) {
        this.start = start;
        this.end = end;
    }

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool(8);

        CountTask task = new CountTask(1, 10000000);

        long start = System.currentTimeMillis();
        ForkJoinTask<Long> result = forkJoinPool.submit(task);

        long start2 = System.currentTimeMillis();
        CountTask task1 = new CountTask(11, 11000000);
        ForkJoinTask<Long> result2 = forkJoinPool.submit(task1);

        LOGGER.info("当前活跃线程数{},{}", forkJoinPool.getActiveThreadCount(), forkJoinPool.getStealCount());

        forkJoinPool.shutdown();

        try {

            LOGGER.info("任务一执行结果:{} 执行耗时：{}", result.get(), System.currentTimeMillis() - start);
            LOGGER.info("任务二执行结果:{} 执行耗时：{}", result2.get(), System.currentTimeMillis() - start2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected Long compute() {
        LOGGER.info("执行{} 和 {}的运算", start, end);


        boolean canCompute = (end - start) <= THRESHOLD;
        if (canCompute) {
            long sum = 0;
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else {
            long sum = 0;
            int middle = (start + end) >> 1;
            CountTask left = new CountTask(start, middle);
            CountTask right = new CountTask(middle + 1, end);

            left.fork();
            right.fork();
            long leftResult = left.join();
            long rightResult = right.join();

            sum = leftResult + rightResult;
            return sum;
        }
    }
}
